package handlers

import (
	"booking-service/internal/models"
	"booking-service/internal/services"
	"booking-service/internal/storage/memory"
	"bytes"
	"encoding/json"
	"github.com/joho/godotenv"
	log "github.com/sirupsen/logrus"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"
	"time"
)

func initializeRoomAvailability(storage *memory.InMemoryRoomAvailabilityStorage) error {
	var err error

	err = storage.UpdateAvailability("reddison", "lux", time.Date(2024, 1, 2, 0, 0, 0, 0, time.UTC), 1)
	if err != nil {
		log.Errorf("Failed to update availability for 2024-01-02: %v", err)
		return err
	}

	err = storage.UpdateAvailability("reddison", "lux", time.Date(2024, 1, 3, 0, 0, 0, 0, time.UTC), 1)
	if err != nil {
		log.Errorf("Failed to update availability for 2024-01-03: %v", err)
		return err
	}

	err = storage.UpdateAvailability("reddison", "lux", time.Date(2024, 1, 4, 0, 0, 0, 0, time.UTC), 1)
	if err != nil {
		log.Errorf("Failed to update availability for 2024-01-04: %v", err)
		return err
	}

	return nil
}

func TestMain(m *testing.M) {
	// Загрузка переменных окружения из .env файла
	err := godotenv.Load()
	if err != nil {
		log.Fatalf("Error loading .env file")
	}

	// Настройка логирования
	logLevel := os.Getenv("LOG_LEVEL")
	if logLevel == "" {
		logLevel = "info" // значение по умолчанию
	}
	level, err := log.ParseLevel(logLevel)
	if err != nil {
		log.Fatalf("Invalid log level: %s", logLevel)
	}
	log.SetLevel(level)
	log.SetFormatter(&log.JSONFormatter{})

	// Запуск тестов
	os.Exit(m.Run())
}

func TestCreateOrder(t *testing.T) {
	orderStorage := &memory.InMemoryOrderStorage{}
	roomStorage := memory.NewInMemoryRoomAvailabilityStorage()
	bookingService := services.NewBookingService(orderStorage, roomStorage)
	handler := NewBookingHandler(bookingService)

	// Предустановка доступности номера
	err := initializeRoomAvailability(roomStorage)
	if err != nil {
		t.Fatalf("Failed to initialize room availability: %v", err)
	}

	// Создание нового заказа
	newOrder := models.Order{
		HotelID:   "reddison",
		RoomID:    "lux",
		UserEmail: "guest@mail.ru",
		From:      time.Date(2024, 1, 2, 0, 0, 0, 0, time.UTC),
		To:        time.Date(2024, 1, 3, 0, 0, 0, 0, time.UTC),
	}

	body, _ := json.Marshal(newOrder)
	req, err := http.NewRequest("POST", "/orders", bytes.NewBuffer(body))
	if err != nil {
		t.Fatal(err)
	}
	rr := httptest.NewRecorder()
	handler.CreateOrder(rr, req)

	if status := rr.Code; status != http.StatusCreated {
		t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusCreated)
	}

	// Проверка, что заказ был добавлен
	orders := orderStorage.GetOrders()
	if len(orders) != 1 {
		t.Errorf("expected 1 order, got %d", len(orders))
	}
}

func TestCreateOrderRoomNotAvailable(t *testing.T) {
	orderStorage := &memory.InMemoryOrderStorage{}
	roomStorage := memory.NewInMemoryRoomAvailabilityStorage()
	bookingService := services.NewBookingService(orderStorage, roomStorage)
	handler := NewBookingHandler(bookingService)

	// Создание нового заказа без предварительной установки доступности номера
	newOrder := models.Order{
		HotelID:   "reddison",
		RoomID:    "lux",
		UserEmail: "guest@mail.ru",
		From:      time.Date(2024, 1, 5, 0, 0, 0, 0, time.UTC),
		To:        time.Date(2024, 1, 6, 0, 0, 0, 0, time.UTC),
	}

	body, _ := json.Marshal(newOrder)
	req, err := http.NewRequest("POST", "/orders", bytes.NewBuffer(body))
	if err != nil {
		t.Fatal(err)
	}
	rr := httptest.NewRecorder()
	handler.CreateOrder(rr, req)

	if status := rr.Code; status != http.StatusInternalServerError {
		t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusInternalServerError)
	}
}
